unit menu_state;

{$mode objfpc}{$H+}

interface

uses glog, SysUtils, sdl2, fgl, input_handler, texture_manager,
  cfg, player, enemy, background, menu_button, animated_game_object, game_object, game_state;

type
  TMenuState = class(TGameState)
  public
    constructor Create(r: PSDL_Renderer);
    (*
    procedure Update; override;
    procedure Render(); override;

    function OnExit: boolean; override;  *)
    function OnEnter: boolean; override;

  private
    procedure PlayClick;

    procedure ExitClick;

    procedure CreateBackground;
  end;

  TPauseState = class(TGameState)
  public
    constructor Create(r: PSDL_Renderer);

    function OnEnter: boolean; override;

  private
    procedure CreateBackground();

    procedure CreateButtons();

    procedure ResumeClick;

    procedure ExitClick;
  end;

  TGameOverState = class(TGameState)
  public
    constructor Create(r: PSDL_Renderer);

    function OnEnter(): boolean; override;

  private
    procedure RestartClick;

    procedure MenuClick;

    procedure CreateBackground;

    procedure CreateLabel();

    procedure CreateButtons();
  end;

  TPlayState = class(TGameState)
  public
    constructor Create(r: PSDL_Renderer);

    function OnEnter: boolean; override;

    procedure Update; override;

  private
    procedure CreateBackground;

    procedure CreatePlayer;

    procedure CreateEnemy;

    function CheckCollision(a, b: TGameObject): boolean;
  end;

implementation

procedure TPlayState.CreatePlayer;
var
  w1, h1: integer;
  go: TGameObject;
begin
  (TTextureManager.Instance()).Load(pr, 'player', 'assets/helicopter0.png');
  (TTextureManager.Instance()).QueryTexture('player', nil,
                                             nil, @w1, @h1);

  go := TPlayer.Create;
  go.Load((WINDOW_WIDTH - w1 div 5) div 2, (WINDOW_HEIGHT - h1) div 2, w1 div 5, h1, 'player');

  objects.Add(go);
end;

procedure TPlayState.CreateEnemy;
var
  w1, h1: integer;
  go: TGameObject;
begin
  (TTextureManager.Instance()).Load(pr, 'enemy', 'assets/helicopter1.png');
  (TTextureManager.Instance()).QueryTexture('enemy', nil,
                                             nil, @w1, @h1);

  go := TEnemy.Create;
  go.Load((WINDOW_WIDTH - w1 div 5) div 2, (WINDOW_HEIGHT - h1) div 2 - 200, w1 div 5, h1, 'enemy');

  objects.Add(go);
end;

function TPlayState.OnEnter: boolean;
begin

  CreateBackground();


  CreatePlayer;
  CreateEnemy;
end;

function TPlayState.CheckCollision(a, b: TGameObject): boolean;
var
  la, ra, ta, ba, lb, rb, tb, bb: single;
begin

  la := a.position.x;
  ra := la + a.w;
  ta := a.position.y;
  ba := ta + a.h;

  lb := b.position.x;
  rb := lb + b.w;
  tb := b.position.y;
  bb := tb + b.h;

  Result := (ta < bb) and (tb < ba) and (la < rb) and (lb < ra);
end;

procedure TPlayState.Update;
var
  s: TGameState;
begin
  inherited Update;
  s := nil;
  if (TInputHandle.Instance()).isKeyDown(SDL_SCANCODE_ESCAPE) then
  begin
    s := TPauseState.Create(pr);
    (TGameStateMachine.Instance()).PushState(s);
  end
  else
    if checkCollision(objects[1], objects[2]) then
      
      begin
        s := TGameOverState.Create(pr);
        (TGameStateMachine.Instance()).ChangeState(s);
      end;
end;

(*
procedure TMenuState.Render();
begin

end;

procedure TMenuState.Update;
begin
end;


function TMenuState.OnExit: boolean;
var
  i: integer;
begin
  if objects <> nil then
  begin
    for i := 0 to objects.Count - 1 do
      objects[i].Free;
    FreeAndNil(objects);
  end;
  Result := True;
end;
   *)

procedure TPlayState.CreateBackground();
var
  w1, h1: integer;
  go: TGameObject;
begin

  (TTextureManager.Instance()).Load(pr, 'background', 'assets/background.png');
  (TTextureManager.Instance()).QueryTexture('background', nil,
                                             nil, @w1, @h1);


  go := TBackground.Create;
  go.Load(0, 0, w1, h1, 'background');
  objects.Add(go);
end;

procedure TMenuState.CreateBackground();
var
  w1, h1: integer;
  go: TGameObject;
begin

  (TTextureManager.Instance()).Load(pr, 'background', 'assets/background.png');
  (TTextureManager.Instance()).QueryTexture('background', nil,
                                             nil, @w1, @h1);


  go := TBackground.Create;
  go.Load(0, 0, w1, h1, 'background');
  objects.Add(go);
end;

function TMenuState.OnEnter: boolean;
var
  btn: TMenuButton;
begin
  (TTextureManager.Instance()).Load(pr, 'play_btn', 'assets/play_button.png');
  (TTextureManager.Instance()).Load(pr, 'exit_btn', 'assets/exit_button.png');

  CreateBackground();

  btn := TMenuButton.Create;
  btn.Load(100, 100, 400, 100, 'play_btn');
  btn.OnClick := @self.PlayClick;
  objects.Add(btn);

  btn := TMenuButton.Create;
  btn.Load(100, 300, 400, 100, 'exit_btn');
  btn.OnClick := @self.ExitClick;
  objects.Add(btn);
  Result := True;
end;

constructor TMenuState.Create(r: PSDL_Renderer);
begin
  inherited Create;
  self.stateId := 'menu';
  self.pr := r;
end;

procedure TMenuState.PlayClick;
var
  state: TGameState;
begin
  readyState := TPlayState.Create(self.pr);
  //(TGameStateMachine.Instance()).ChangeState(state);
end;

procedure TMenuState.ExitClick;
begin
  (TInputHandle.Instance()).IsQuit := True;
end;


procedure TGameOverState.RestartClick;
var
  state: TGameState;
begin
  readyState := TPlayState.Create(self.pr);
  //(TGameStateMachine.Instance()).ChangeState(state);
end;

procedure TGameOverState.MenuClick;
var
  state: TGameState;
begin
  readyState := TMenuState.Create(self.pr);
  //(TGameStateMachine.Instance()).ChangeState(state);
end;

constructor TPlayState.Create(r: PSDL_Renderer);
begin
  inherited Create;
  self.stateId := 'play';
  self.pr := r;
end;


constructor TPauseState.Create(r: PSDL_Renderer);
begin
  inherited Create;
  self.stateId := 'pause';
  self.pr := r;
end;

procedure TPauseState.CreateBackground();
var
  w1, h1: integer;
  go: TGameObject;
begin

  (TTextureManager.Instance()).Load(pr, 'pause_background', 'assets/background.png');
  (TTextureManager.Instance()).QueryTexture('pause_background', nil,
                                             nil, @w1, @h1);


  go := TBackground.Create;
  go.Load(0, 0, w1, h1, 'pause_background');
  objects.Add(go);

end;

procedure TPauseState.CreateButtons();
var
  w1, h1: integer;
  go: TMenuButton;
begin
  (TTextureManager.Instance()).Load(pr, 'btn_main', 'assets/main_menu_button.png');
  (TTextureManager.Instance()).Load(pr, 'btn_resume', 'assets/resume_button.png');
  (TTextureManager.Instance()).QueryTexture('btn_main', nil, nil, @w1, @h1);

  go := TMenuButton.Create;
  go.Load((WINDOW_WIDTH - (w1 div 3)) div 2, WINDOW_HEIGHT div 2 - h1 div 2, w1 div 3, h1, 'btn_main');

  go.OnClick := @self.ExitClick;
  objects.Add(go);


  go := TMenuButton.Create;
  go.Load((WINDOW_WIDTH - (w1 div 3)) div 2, 3 * WINDOW_HEIGHT div 4 - h1 div 2, w1 div 3, h1, 'btn_resume');
  go.OnClick := @self.ResumeClick;
  objects.Add(go);
end;

function TPauseState.OnEnter: boolean;
begin
  CreateBackground();
  CreateButtons();
end;

procedure TPauseState.ResumeClick;
begin
  writelnlog('btn resume click');
  (TGameStateMachine.Instance()).popState;
end;

procedure TPauseState.ExitClick;
var
  state: TGameState;
begin
  writelnlog('btn exit to menu click');
  readyState := TMenuState.Create(pr);
  //(TGameStateMachine.Instance()).changeState(state);
end;

constructor TGameOverState.Create(r: PSDL_Renderer);
begin
  inherited Create;
  self.stateId := 'gameover';
  self.pr := r;
end;

procedure TGameOverState.CreateLabel();
var
  w1, h1: integer;
  go: TAnimatedGameObject;
begin
  (TTextureManager.Instance()).Load(pr, 'gameover_label', 'assets/gameover.png');
  (TTextureManager.Instance()).QueryTexture('gameover_label', nil,
                                             nil, @w1, @h1);

  go := TAnimatedGameObject.Create;
  go.Load((WINDOW_WIDTH - (w1 div 2)) div 2, WINDOW_HEIGHT div 4 - h1 div 2, w1 div 2, h1, 'gameover_label');
  go.AnimationSpeed := 2;
  objects.Add(go);
end;

procedure TGameOverState.CreateButtons();
var
  w1, h1: integer;
  go: TMenuButton;
begin
  (TTextureManager.Instance()).Load(pr, 'btn_main', 'assets/main_menu_button.png');
  (TTextureManager.Instance()).Load(pr, 'btn_restart', 'assets/restart_button.png');
  (TTextureManager.Instance()).QueryTexture('btn_main', nil, nil, @w1, @h1);

  go := TMenuButton.Create;
  go.Load((WINDOW_WIDTH - (w1 div 3)) div 2, WINDOW_HEIGHT div 2 - h1 div 2, w1 div 3, h1, 'btn_main');

  go.OnClick := @self.MenuClick;
  objects.Add(go);


  go := TMenuButton.Create;
  go.Load((WINDOW_WIDTH - (w1 div 3)) div 2, 3 * WINDOW_HEIGHT div 4 - h1 div 2, w1 div 3, h1, 'btn_restart');
  go.OnClick := @self.RestartClick;
  objects.Add(go);
end;

function TGameOverState.OnEnter(): boolean;
begin
  CreateBackground();
  CreateLabel();
  CreateButtons();
end;

procedure TGameOverState.CreateBackground();
var
  w1, h1: integer;
  go: TGameObject;
begin

  (TTextureManager.Instance()).Load(pr, 'gameover_background', 'assets/background.png');
  (TTextureManager.Instance()).QueryTexture('gameover_background', nil,
                                             nil, @w1, @h1);


  go := TBackground.Create;
  go.Load(0, 0, w1, h1, 'gameover_background');
  objects.Add(go);
end;

end.
